home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 July: Mac OS SDK / Dev.CD Jul 96 SDK / Dev.CD Jul 96 SDK1.toast / Development Kits (Disc 1) / OpenDoc Development Framework / Tools & Goodies / IntlTest / Sources / EditViews.cpp < prev    next >
Encoding:
Text File  |  1996-04-23  |  17.9 KB  |  671 lines  |  [TEXT/MPS ]

  1. //========================================================================================
  2. //
  3. //    File:                EditViews.h
  4. //    Release Version:    $ ODF 1 $
  5. //
  6. //    Author:                Mary Boetcher
  7. //
  8. //    Copyright:            (c) 1993 - 1996 by Apple Computer, Inc., all rights reserved.
  9. //
  10. //========================================================================================
  11.  
  12. #include "IntlTest.hpp"
  13.  
  14. #ifndef EDITVIEWS_H
  15. #include "EditViews.h"
  16. #endif
  17.  
  18. #ifndef DEFINES_K
  19. #include "Defines.k"
  20. #endif
  21.  
  22. #ifndef COMMANDS_H
  23. #include "Commands.h"
  24. #endif
  25.  
  26. // ----- Part Layer -----
  27.  
  28. #ifndef FWEDVIEW_H
  29. #include "FWEdView.h"
  30. #endif
  31.  
  32. #ifndef FWEVENT_H
  33. #include "FWEvent.h"
  34. #endif
  35.  
  36. #ifndef FWCONTXT_H
  37. #include "FWContxt.h"
  38. #endif
  39.  
  40. #ifndef FWFRAME_H
  41. #include "FWFrame.h"
  42. #endif
  43.  
  44. // ----- Foundation Layer -----
  45.  
  46. #ifndef FWINTERE_H
  47. #include "FWIntere.h"
  48. #endif
  49.  
  50. // ----- Macintosh Includes -----
  51.  
  52. #ifndef __SCRIPT__
  53. #include <Script.h>
  54. #endif
  55.  
  56. #ifndef __GESTALT__
  57. #include <Gestalt.h>
  58. #endif
  59.  
  60. #ifndef __AEPACKOBJECT__
  61. #include <AEPackObject.h>
  62. #endif
  63.  
  64. //========================================================================================
  65. // RunTime Info
  66. //========================================================================================
  67.  
  68. #ifdef FW_BUILD_MAC
  69. #pragma segment odfIntlTest
  70. #endif
  71.  
  72. //========================================================================================
  73. // Constants and Globals
  74.  
  75. FW_CFont gFontOsaka(FW_CString32("Osaka"), FW_kPlain, FW_IntToFixed(14));
  76.  
  77. #define cTypingCommand 110
  78. #define cTSMTypingCommand 111
  79.  
  80. //----------------------------------------------------------------------------------------
  81. // Pre- and post-update callback procs for TSMTE
  82.  
  83. pascal void MyTSMTEPreUpdateProc(TEHandle textH, long refCon);
  84.  
  85. pascal void MyTSMTEPostUpdateProc(TEHandle textH, 
  86.                                   long fixLen, long inputAreaStart, long inputAreaEnd, 
  87.                                   long pinStart, long pinEnd, long refCon);
  88.  
  89. static TSMTEPreUpdateUPP gTSMTEPreUpdateUPP = NULL;
  90. static TSMTEPostUpdateUPP gTSMTEPostUpdateUPP = NULL;
  91.  
  92. //========================================================================================
  93. // TSMTE callback routines
  94. //========================================================================================
  95.  
  96. //----------------------------------------------------------------------------------------
  97. pascal void MyTSMTEPreUpdateProc(TEHandle textH, long refCon)
  98. {
  99.     FW_TRY
  100.     {
  101.         CJapEditView* editView = (CJapEditView*)refCon;    /* !!! */
  102.     
  103.         if (editView->IsFirstEventInSequence())
  104.         {
  105.             //--- Make a new typing command and save the Undo state
  106.             editView->DoMakeTypingCommand();
  107.         }
  108.     }
  109.     FW_CATCH_BEGIN
  110.     FW_CATCH_EVERYTHING()
  111.     {
  112.         // do nothing; no way to return an error
  113.     }
  114.     FW_CATCH_END
  115. }
  116.  
  117. //----------------------------------------------------------------------------------------
  118. pascal void MyTSMTEPostUpdateProc(TEHandle textH, 
  119.                                   long fixLen, long inputAreaStart, long inputAreaEnd, 
  120.                                   long pinStart, long pinEnd, long refCon)
  121. {
  122.     // fixLen is the length of the confirmed text in bytes.
  123.     FW_UNUSED(inputAreaStart);
  124.     FW_UNUSED(inputAreaEnd);
  125.     FW_UNUSED(pinStart);
  126.     FW_UNUSED(pinEnd);
  127.     FW_TRY
  128.     {
  129.         if (fixLen > 0)        // some characters were confirmed
  130.         {
  131.             CJapEditView* editView = (CJapEditView*)refCon;    /* !!! */
  132.             Environment* ev = somGetGlobalEnvironment();
  133.  
  134.             //--- Add the confirmed characters to the typing command
  135.             char* p = (char*) (*((**textH).hText)) + pinEnd - fixLen;
  136.             CTSMInput input(p, fixLen);
  137.             editView->AddInput(ev, &input);
  138.     
  139.             //--- Tell the edit view to notify the document that it's been changed
  140.             editView->Notify(ev, CEditNotification(editView));
  141.         }
  142.     }
  143.     FW_CATCH_BEGIN
  144.     FW_CATCH_EVERYTHING()
  145.     {
  146.         // do nothing; no way to return an error
  147.     }
  148.     FW_CATCH_END
  149. }
  150.  
  151. //========================================================================================
  152. // FW_MTSMHandler
  153. //========================================================================================
  154.  
  155. FW_DEFINE_CLASS_M0(FW_MTSMHandler)
  156.  
  157. //----------------------------------------------------------------------------------------
  158. FW_MTSMHandler::FW_MTSMHandler(FW_CEditView* theView)
  159. {
  160.     fEditView = theView;
  161.     fTSMDocId = NULL;
  162.     fTSMHandle = NULL;
  163.     fError = noErr;
  164. }
  165.  
  166. //----------------------------------------------------------------------------------------
  167. FW_MTSMHandler::~FW_MTSMHandler()
  168. {
  169.     if (fTSMDocId)
  170.         fError = ::DeleteTSMDocument(fTSMDocId);
  171.     fTSMHandle = NULL;
  172.     fEditView = NULL;
  173.  
  174.     // Dispose any UPPs we made
  175.     if (gTSMTEPreUpdateUPP)
  176.     {
  177.         DisposeRoutineDescriptor(gTSMTEPreUpdateUPP);
  178.         gTSMTEPreUpdateUPP = NULL;
  179.     }
  180.     if (gTSMTEPostUpdateUPP)
  181.     {
  182.         DisposeRoutineDescriptor(gTSMTEPostUpdateUPP);
  183.         gTSMTEPostUpdateUPP = NULL;
  184.     }
  185. }
  186.  
  187. //----------------------------------------------------------------------------------------
  188. FW_Boolean FW_MTSMHandler::CreateTSMDocument(TEHandle te)
  189. {
  190.     FW_Boolean result = false;
  191.  
  192.     // Check for the presence of TSMTE
  193.     long gestaltResponse;
  194.     ODBoolean hasTSMTE;
  195.     if (Gestalt(gestaltTSMTEAttr, &gestaltResponse) == noErr)
  196.         hasTSMTE = (gestaltResponse & (1<<gestaltTSMTEPresent) != 0);
  197.  
  198.     if (hasTSMTE)    // Don't create a TSM document if TSMTE is not present
  199.     {
  200.         TSMDocumentID id = NULL;
  201.         InterfaceTypeList supportedTypes;
  202.         supportedTypes[0] = kTSMTEInterfaceType;
  203.         TSMTERecHandle tsmHandle;
  204.     
  205.         fError = ::NewTSMDocument(1, supportedTypes, &id, (long) &tsmHandle);
  206.         if (fError == noErr)
  207.         {
  208.             // Create UPPs for pre- and post-update callbacks
  209.             gTSMTEPreUpdateUPP = NewTSMTEPreUpdateProc(&MyTSMTEPreUpdateProc);
  210.             gTSMTEPostUpdateUPP = NewTSMTEPostUpdateProc(&MyTSMTEPostUpdateProc);
  211.  
  212.             // Initialize the TSM record
  213.             fTSMDocId = id;
  214.             fTSMHandle = tsmHandle;
  215.             (*tsmHandle)->textH = te;
  216.             (*tsmHandle)->preUpdateProc = gTSMTEPreUpdateUPP;
  217.             (*tsmHandle)->postUpdateProc = gTSMTEPostUpdateUPP;
  218.             (*tsmHandle)->updateFlag = kTSMTEAutoScroll;
  219.             (*tsmHandle)->refCon = (long)fEditView; /* !!! */
  220.             result = true;
  221.         }
  222.     }
  223.  
  224.     // Copied from Sample TSMTE DragText
  225.     ::UseInputWindow( kODNULL, false);
  226.  
  227.     return result;
  228. }
  229.  
  230. //----------------------------------------------------------------------------------------
  231. FW_Boolean FW_MTSMHandler::DoActivateTSM(FW_Boolean becomingActive)
  232. {
  233.     FW_Boolean result = false;
  234.  
  235.     if (fTSMDocId)
  236.     {
  237.         if (becomingActive)
  238.         {
  239.             fError = ::ActivateTSMDocument(fTSMDocId);
  240.  
  241.             // Copied from Sample TSMTE DragText
  242.             ::UseInputWindow( kODNULL, false);
  243.         }
  244.         else
  245.             fError = ::DeactivateTSMDocument(fTSMDocId);
  246.         if (fError == noErr)
  247.             result = true;
  248.     }
  249.  
  250.     return result;
  251. }
  252.  
  253. //----------------------------------------------------------------------------------------
  254. FW_Boolean FW_MTSMHandler::DoFixTSMDocument()
  255. {
  256.     FW_Boolean result = false;
  257.  
  258.     if (fTSMDocId)
  259.     {
  260.         fError = ::FixTSMDocument(fTSMDocId);
  261.         if (fError == noErr)
  262.             result = true;
  263.     }
  264.  
  265.     return result;
  266. }
  267.  
  268. //========================================================================================
  269. // CJapEditView - for editing Japanese script
  270. //========================================================================================
  271.  
  272. FW_DEFINE_AUTO(CJapEditView)
  273.  
  274. FW_DEFINE_CLASS_M2(CJapEditView, CMyEditView, FW_MTSMHandler);
  275.  
  276. //----------------------------------------------------------------------------------------
  277. CJapEditView::CJapEditView(Environment* ev,
  278.                         FW_CSuperView* container, 
  279.                         ODID viewId,
  280.                         const FW_CRect& bounds,
  281.                         const FW_CFont& font,
  282.                         short maxChars,
  283.                         unsigned short attributes)
  284. :    CMyEditView(ev, container, viewId, bounds, font, maxChars, attributes),
  285.     FW_MTSMHandler(this),
  286.     fTSMTypingCommand(NULL),
  287.     fMyFont(0),
  288.     fMyFontScript(smJapanese),
  289.     fPreviousFontScript(0),
  290.     fFirstActivation(true)
  291. {
  292. }
  293.  
  294. //----------------------------------------------------------------------------------------
  295. CJapEditView::~CJapEditView()
  296. {
  297. }
  298.  
  299. //----------------------------------------------------------------------------------------
  300. // CJapEditView::ActivateTarget
  301. //----------------------------------------------------------------------------------------
  302. void CJapEditView::ActivateTarget(Environment* ev, FW_Boolean tabSelection)
  303. {
  304.     // Save the user's keyboard script
  305.     fPreviousFontScript = ::GetScriptManagerVariable(smKeyScript);
  306.  
  307.     if (fFirstActivation)
  308.     {
  309.         ::KeyScript(fMyFontScript);
  310.         fFirstActivation = false;
  311.     }
  312.  
  313.     // Activate TSM
  314.     if (!this->DoActivateTSM(true))
  315.     {
  316.         // Set the keyboard script to match my font's script, if necessary
  317.         if (fMyFontScript != fPreviousFontScript)
  318.             ::KeyScript(fMyFontScript);
  319.     }
  320.  
  321.     // Call inherited
  322.     FW_CEditView::ActivateTarget(ev, tabSelection);
  323. }
  324.  
  325. //----------------------------------------------------------------------------------------
  326. // CJapEditView::DeactivateTarget
  327. //----------------------------------------------------------------------------------------
  328. void CJapEditView::DeactivateTarget(Environment* ev)
  329. {
  330.     // Call inherited
  331.     CMyEditView::DeactivateTarget(ev);
  332.  
  333.     // Deactivate TSM
  334.     if (!this->DoActivateTSM(false))
  335.     {
  336.         // Restore the user's keyboard script
  337.         ::KeyScript(fPreviousFontScript);
  338.     }
  339. }
  340.  
  341. //----------------------------------------------------------------------------------------
  342. // CJapEditView::DoMenu
  343. //----------------------------------------------------------------------------------------
  344. FW_Boolean CJapEditView::DoMenu(Environment* ev, const FW_CMenuEvent& theMenuEvent) // Override
  345. {
  346.     FW_Boolean menuHandled = true;
  347.     ODCommandID id = theMenuEvent.GetCommandID(ev);
  348.     
  349.     switch (id)
  350.     {
  351.         case kODCommandCut:
  352.         case kODCommandCopy:
  353.         case kODCommandPaste:
  354.         case kODCommandClear:
  355.         case kODCommandSelectAll: {
  356.             menuHandled = CMyEditView::DoMenu(ev, theMenuEvent);
  357.             this->DoFixTSMDocument();
  358.             break;
  359.         }
  360.  
  361.         default:
  362.             menuHandled = FW_CEditView::DoMenu(ev, theMenuEvent);
  363.     }
  364.  
  365.     return menuHandled;
  366. }
  367.  
  368. //----------------------------------------------------------------------------------------
  369. void CJapEditView::InitJapEditView(Environment* ev)
  370. {
  371.     // Create a TSM document, if TSMTE is present
  372.     this->CreateTSMDocument((TEHandle)GetPlatformEditHandle(ev));
  373.  
  374.     // Save the font number
  375.     fMyFont = gFontOsaka.MacGetFontID();
  376. //    FW_ASSERT(fMyFontScript == ::FontToScript(fMyFont));
  377.  
  378.     // Set the font to Osaka - already done in constructor
  379. //    FW_CEditView::SetFont(ev, gFontOsaka);
  380. }
  381.  
  382. //-----------------------------------------------------------------------------------------
  383. void CJapEditView::AddInput(Environment* ev, CTSMInput* input)
  384. {
  385.     FW_ASSERT(fTSMTypingCommand);
  386.     fTSMTypingCommand->AddInput(ev, input);
  387. }
  388.  
  389. //-----------------------------------------------------------------------------------------
  390. FW_Boolean CJapEditView::IsFirstEventInSequence()
  391. {
  392.     if (fTSMTypingCommand == NULL) return true;
  393.     return fTSMTypingCommand->IsCompleted();
  394. }
  395.  
  396. //-----------------------------------------------------------------------------------------
  397. void CJapEditView::DoMakeTypingCommand(Environment* ev)
  398. {
  399.     // If called by a callback routine, there's no SOM variable
  400.     if (ev == NULL)
  401.         ev = somGetGlobalEnvironment();
  402.  
  403.     this->DoneTyping(ev);    // this was already called, presumably...
  404.  
  405.     fTSMTypingCommand = NewTypingCommand(ev, NULL);    // no input yet
  406.     fTypingCommand->Execute(ev, false);                // calls DoIt, which calls SaveUndoState
  407. }
  408.  
  409. //-----------------------------------------------------------------------------------------
  410. CTSMTypingCommand* CJapEditView::NewTypingCommand(Environment* ev, CTSMInput* firstInput)
  411. {
  412.     CTSMTypingCommand* cmd = FW_NEW(CTSMTypingCommand, (ev, cTSMTypingCommand, GetFrame(ev),
  413.                                                         this, firstInput));
  414.     fTypingCommand = cmd;
  415.     return cmd;
  416. }
  417.  
  418. //-----------------------------------------------------------------------------------------
  419. FW_Boolean CJapEditView::DoCharKey(Environment* ev, const FW_CCharKeyEvent& event)
  420. {
  421.     // Ignore Command-characters which are not associated with menu commands
  422.     if (event.GetModifiers() & cmdKey)
  423.         return false;
  424.  
  425.     char ch = event.GetChar(ev);
  426.  
  427.     if (IsArrowKey(ch))            // arrow keys
  428.     {
  429.         this->DoneTyping(ev);
  430.     }
  431.     else if (ch == chBackspace)
  432.     {
  433.         if (this->IsFirstEventInSequence())
  434.         {
  435.             //--- Make a new typing command and save the Undo state
  436.             this->DoMakeTypingCommand(ev);
  437.         }
  438.         fTSMTypingCommand->Backspace(ev);
  439.     }
  440.     else    // user typed a single-byte character, such as a CR
  441.     {
  442.         //--- Make sure we have room for the character
  443.         if (PrivCheckMaxChars(1))
  444.         {
  445.             FW_Beep();
  446.             return true;
  447.         }
  448.  
  449.         if (ch == chReturn)    // CR
  450.         {
  451.             this->DoneTyping(ev);
  452.         }
  453.  
  454.         //--- Pass character to the typing command
  455.         CTSMInput input(ch);
  456.         if (fTSMTypingCommand && fTSMTypingCommand->IsNotCompleted())
  457.             fTSMTypingCommand->AddInput(ev, &input);
  458.         else
  459.         {
  460.             fTSMTypingCommand = NewTypingCommand(ev, &input);
  461.             fTSMTypingCommand->Execute(ev, false);        // DoIt; don't delete if not undoable
  462.         }
  463.     }
  464.  
  465.     //--- Tell TextEdit to handle the character
  466.     FW_CEditView::InputCharKey(ev, ch);
  467.     return true;
  468. }
  469.  
  470. //========================================================================================
  471. //    CLASS CEditNotification
  472. //========================================================================================
  473.  
  474. //----------------------------------------------------------------------------------------
  475. // CEditNotification constructors
  476. //----------------------------------------------------------------------------------------
  477.  
  478. CEditNotification::CEditNotification(FW_CEditView* editView) :
  479.     FW_CNotification()
  480. {
  481.     fEditView = editView;
  482.     SetInterest(FW_CInterest((FW_MNotifier*)editView, kEditViewMsg));
  483. }
  484.  
  485. //----------------------------------------------------------------------------------------
  486. CEditNotification::CEditNotification(const CEditNotification& other) :
  487.     FW_CNotification(other),
  488.     fEditView(other.fEditView)
  489. {
  490. }
  491.  
  492. //----------------------------------------------------------------------------------------
  493. // CEditNotification destructor
  494. //----------------------------------------------------------------------------------------
  495.  
  496. CEditNotification::~CEditNotification()
  497. {
  498. }
  499.  
  500. //----------------------------------------------------------------------------------------
  501. // CEditNotification::operator=
  502. //----------------------------------------------------------------------------------------
  503.  
  504. CEditNotification& CEditNotification::operator= (const CEditNotification& other)
  505. {
  506.     if (this != &other)
  507.     {
  508.         FW_CNotification::operator=(other);
  509.         fEditView = other.fEditView;
  510.     }
  511.     return *this;
  512. }
  513.  
  514. //========================================================================================
  515. // CMyEditView - for editing 1-byte scripts
  516. //========================================================================================
  517.  
  518. FW_DEFINE_AUTO(CMyEditView)
  519.  
  520. FW_DEFINE_CLASS_M1(CMyEditView, FW_CEditView);
  521.  
  522. //----------------------------------------------------------------------------------------
  523. CMyEditView::CMyEditView(Environment* ev,
  524.                          FW_CSuperView* container,
  525.                          ODID viewId,
  526.                          const FW_CRect& bounds,
  527.                          const FW_CFont& font,
  528.                          short maxChars,
  529.                          unsigned short attributes)
  530. :    FW_CEditView(ev, container, viewId, bounds, "", font, maxChars, attributes),
  531.     fTypingCommand(NULL)
  532. {
  533. }
  534.  
  535. //----------------------------------------------------------------------------------------
  536. CMyEditView::~CMyEditView()
  537. {
  538. }
  539.  
  540. //-----------------------------------------------------------------------------------------
  541. FW_Boolean CMyEditView::DoCharKey(Environment* ev, const FW_CCharKeyEvent& event)
  542. {
  543.     // Ignore Command-characters which are not associated with menu commands
  544.     if (event.GetModifiers() & cmdKey)
  545.         return false;
  546.  
  547.     char ch = event.GetChar(ev);
  548.  
  549.     if (IsArrowKey(ch))            // arrow keys
  550.     {
  551.         this->DoneTyping(ev);
  552.     }
  553.     else
  554.     {
  555.         if (ch != chBackspace)
  556.         {
  557.             //--- Make sure we have room for the character
  558.             if (PrivCheckMaxChars(1))
  559.             {
  560.                 FW_Beep();
  561.                 return true;
  562.             }
  563.     
  564.             if (ch == FW_PlatformNewLineChar)    // CR
  565.             {
  566.                 this->DoneTyping(ev);
  567.             }
  568.         }
  569.  
  570.         //--- Pass character to the typing command
  571.         if (fTypingCommand && fTypingCommand->IsNotCompleted())
  572.             fTypingCommand->AddCharacter(ev, ch);
  573.         else
  574.         {
  575.             fTypingCommand = NewTypingCommand(ev, ch);
  576.             fTypingCommand->Execute(ev, false);    // don't delete if not undoable
  577.         }
  578.     }
  579.  
  580.     //--- Tell TextEdit to handle the character
  581.     FW_CEditView::InputCharKey(ev, ch);
  582.     return true;
  583. }
  584.  
  585. //-----------------------------------------------------------------------------------------
  586. FW_Boolean CMyEditView::DoMouseDown(Environment* ev, const FW_CMouseEvent& event)
  587. {
  588.     this->DoneTyping(ev);
  589.     return FW_CEditView::DoMouseDown(ev, event);
  590. }
  591.  
  592. //-----------------------------------------------------------------------------------------
  593. void CMyEditView::DoneTyping(Environment* ev)
  594. {
  595.     if (fTypingCommand)
  596.     {
  597.         fTypingCommand->CompleteTyping(ev);
  598.     }
  599. }
  600.  
  601. //-----------------------------------------------------------------------------------------
  602. FW_Boolean CMyEditView::IsArrowKey(char ch)
  603. {
  604.     switch (ch)
  605.     {
  606.         case chLeft:
  607.         case chRight:
  608.         case chUp:
  609.         case chDown:
  610.             return true;
  611.     }
  612.     return false;
  613. }
  614.  
  615. //-----------------------------------------------------------------------------------------
  616. CTypingCommand* CMyEditView::NewTypingCommand(Environment* ev, char firstChar)
  617. {
  618.     CTypingCommand* cmd = FW_NEW(CTypingCommand, (ev, cTypingCommand, GetFrame(ev),
  619.                                                   this, true, firstChar));
  620.     return cmd;
  621. }
  622.  
  623. //----------------------------------------------------------------------------------------
  624. FW_Boolean CMyEditView::DoMenu(Environment* ev, const FW_CMenuEvent& theMenuEvent) // Override
  625. {
  626.     FW_Boolean menuHandled = true;
  627.     ODCommandID id = theMenuEvent.GetCommandID(ev);
  628.     
  629.     switch (id)
  630.     {
  631.         case kODCommandCut: 
  632.         case kODCommandCopy: 
  633.         case kODCommandPaste: 
  634.         case kODCommandClear:
  635.         {    
  636.             this->DoneTyping(ev);
  637.             // Create and execute one of our undoable clipboard commands
  638.             FW_CClipboardCommand* cmd = GetFrame(ev)->NewClipboardCommand(ev, id);
  639.             if (cmd)
  640.                 cmd->Execute(ev);
  641.             break;
  642.         }
  643.  
  644.         case kODCommandSelectAll:
  645.             this->DoneTyping(ev);
  646.             // fall thru to default case
  647.  
  648.         default:
  649.             menuHandled = FW_CEditView::DoMenu(ev, theMenuEvent);    // for Select All or whatever
  650.     }
  651.  
  652.     return menuHandled;
  653. }
  654.  
  655. //----------------------------------------------------------------------------------------
  656. void CMyEditView::DeactivateTarget(Environment* ev)
  657. {
  658.     // finish the typing command
  659.     this->DoneTyping(ev);
  660.  
  661.     // call inherited
  662.     FW_CEditView::DeactivateTarget(ev);
  663. }
  664.  
  665. //----------------------------------------------------------------------------------------
  666. void CMyEditView::LinkToReceiver(FW_MReceiver* receiver)
  667. {
  668.     receiver->AddInterest(FW_CInterest(this, kEditViewMsg));
  669. }
  670.  
  671.